package com.yuw.reflectiondemo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class TestDriver {
    public static void main(String[] args) {
        System.out.println("=============================");
        test01();
        System.out.println("=============================");
        test02();
        System.out.println("=============================");
        test03();
        System.out.println("=============================");
        test04();

    }

    /**
     * 反射工具类：Field工具类
     */
    public static void test04() {
        // (3) 实例对象.getClass方法
        Student student = new Student();
        Class clazz2 = student.getClass(); // 继承自Object类的方法
        try {
            // 获取一个指定名字的方法对象
            Method method = clazz2.getDeclaredMethod("doStuding", String.class);
            // 使用invoke调用method对象，让该方法对象动态执行起来
            method.invoke(student, "tjise2");
            //student.doStuding();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 反射工具类：Field工具类
     */
    public static void test03() {
        // (3) 实例对象.getClass方法
        Student student = new Student();
        Class clazz2 = student.getClass(); // 继承自Object类的方法
        try {
            // 获取一个指定名字的属性对象
            Field field = clazz2.getDeclaredField("stuName");
            // 设值属性对象可以操作私有属性
            field.setAccessible(true);
            // 调用属性对象的set方法，给属性对象进行设值；需要绑定该属性来自的实例对象
            field.set(student, "zhangsan");
            System.out.println(student);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 反射工具类：Constructor工具类
     */
    public static void test02() {
        // 获取 类 描述类 Class的三种途径：
        // (1)类名.class
        Class<Student> clazz = Student.class;
        try {
            // 获取类的构造方法对象
            Constructor<Student> constructor =
                    clazz.getDeclaredConstructor(String.class, String.class, double.class);
            // 调用构造方法对象的newInstance方法创建一个实例对象
            Student student = constructor.newInstance("战三", "10010", 90);
            System.out.println("通过构造方法对象获取的实例变量：");
            System.out.println(student);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 反射工具类：Class工具类
     */
    public static void test01() {
        // 获取 类 描述类 Class的三种途径：
        // (1)类名.class
        Class<Student> clazz = Student.class;
        // (2)Class的forName静态方法
        try {
            Class clazz1 = Class.forName("com.yuw.reflectiondemo.Student"); // 包路径名
            System.out.println("clazz == clazz1:" + (clazz == clazz1));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        // (3) 实例对象.getClass方法
        Student student = new Student();
        Class clazz2 = student.getClass(); // 继承自Object类的方法

        // 课堂提问： clazz、clazz1、clazz2 是同一个对象么？
        System.out.println("clazz == clazz2:" + (clazz == clazz2));

        try {
            // 通过Class获取这个类的实例对象
            Student student1 = clazz.newInstance(); // 等价于new

        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
